package ru.zombator.taskman.core.dbclient;

import java.util.List;

import ru.zombator.taskman.core.domain.Datestamp;
import ru.zombator.taskman.core.domain.IManager;
import ru.zombator.taskman.core.domain.IPerson;
import ru.zombator.taskman.core.domain.ITask;
import ru.zombator.taskman.core.domain.ITaskProject;
import ru.zombator.taskman.core.domain.IWorkTime;
import ru.zombator.taskman.core.domain.IWorker;

/**
 * Интерфейс клиента базы данных.
 * <p>
 * Определяет основные операции уровня доступа к данным
 * 
 * @author nvamelichev
 * 
 */
public interface IDbClient {
	/**
	 * Роль пользователя в проекте
	 */
	public enum Role {
		/**
		 * исполнитель
		 */
		WORKER,
		/**
		 * менеджер
		 */
		MANAGER,
	}

	/**
	 * Добавляет пользователя с заданным именем, IP-адресом и ролью.
	 * 
	 * @param name
	 *            - имя пользователя
	 * @param ipAddress
	 *            - IP-адрес
	 * @param role
	 *            - роль
	 * @throws DbException
	 *             не удалось
	 * @return созданный пользователь
	 */
	IPerson addUser(String name, String ipAddress, Role role)
			throws DbException;

	/**
	 * Изменяет атрибуты заданного пользователя.
	 * 
	 * @param user
	 *            - измененный пользователь
	 * @throws DbException
	 *             не удалось
	 */
	void changeUser(IPerson user) throws DbException;

	/**
	 * Удаляет заданного пользователя
	 * 
	 * @param user
	 *            - пользователь для удаления
	 * @throws DbException
	 *             не удалось
	 */
	void dropUser(IPerson user) throws DbException;

	/**
	 * Возвращает пользователя по IP-адресу
	 * 
	 * @param ipAddress
	 *            - IP-адрес
	 * @throws DbException
	 *             не удалось
	 * @return пользователь с данным адресом; <code>null</code>, если такого
	 *         пользователя нет
	 */
	IPerson getUser(String ipAddress) throws DbException;

	/**
	 * Создает проект
	 * 
	 * @param manager
	 *            - создатель проекта
	 * @param name
	 *            - имя проекта
	 * @param password
	 *            - пароль проекта
	 * @throws DbException
	 *             не удалось
	 * @return созданный проект
	 */
	ITaskProject createProject(IManager manager, String name, String password)
			throws DbException;

	/**
	 * Присоединяет менеджера к проекту
	 * 
	 * @param manager
	 *            - присоединяемый менеджер
	 * @param project
	 *            - проект
	 * @param password
	 *            - пароль проекта
	 * @throws DbException
	 *             не удалось
	 */
	void joinProject(IManager manager, ITaskProject project, String password)
			throws DbException;

	/**
	 * Возвращает полный список проектов
	 * 
	 * @throws DbException
	 *             не удалось
	 * @return все проекты
	 */
	List<ITaskProject> getProjects() throws DbException;

	/**
	 * Возвращает полный список проектов, которыми управляет или в выполнении
	 * которых задействован указанный пользователь
	 * 
	 * @param user
	 *            - участник проекта
	 * @throws DbException
	 *             не удалось
	 * @return все проекты пользователя
	 */
	List<ITaskProject> getMyProjects(IPerson user) throws DbException;

	/**
	 * Создает задачу
	 * 
	 * @param manager
	 *            - менеджер проекта
	 * @param project
	 *            - проект
	 * @param name
	 *            - имя задачи
	 * @param startsWhen
	 *            - плановая дата начала
	 * @param endsWhen
	 *            - плановая дата окончания
	 * @throws DbException
	 *             не удалось
	 * @return задача
	 */
	ITask createTask(IManager manager, ITaskProject project, String name,
			Datestamp startsWhen, Datestamp endsWhen) throws DbException;

	/**
	 * Задает описание задачи
	 * 
	 * @param manager
	 *            - менеджер проекта, в котором задача
	 * @param task
	 *            - измененная задача
	 * @throws DbException
	 *             не удалось
	 * @return задача
	 */
	void setTaskDescription(IManager manager, ITask task) throws DbException;

	/**
	 * Задает состояние задачи
	 * 
	 * @param worker
	 *            - исполнитель
	 * @param task
	 *            - измененная задача
	 * @throws DbException
	 *             не удалось
	 * @return задача
	 */
	void setTaskStatus(IWorker worker, ITask task) throws DbException;

	/**
	 * Назначает задачу работнику
	 * 
	 * @param manager
	 *            - менеджер проекта
	 * @param task
	 *            - задача
	 * @param worker
	 *            - исполнитель
	 * @throws DbException
	 *             не удалось
	 * @return задача
	 */
	void assignWorkerToTask(IManager manager, ITask task, IWorker worker)
			throws DbException;

	/**
	 * Снимает задачу с работника
	 * 
	 * @param manager
	 *            - менеджер проекта
	 * @param task
	 *            - задача
	 * @param worker
	 *            - исполнитель
	 * @throws DbException
	 *             не удалось
	 * @return задача
	 */
	void unAssignWorker(IManager manager, ITask task, IWorker worker)
			throws DbException;

	/**
	 * Отмечает время, проведенное за выполнением задачи
	 * 
	 * @param worker
	 *            - исполнитель
	 * @param task
	 *            - задача
	 * @param date
	 *            - дата работы
	 * @param hours
	 *            - количество часов работы
	 * @throws DbException
	 *             не удалось
	 */
	void trackTime(IWorker worker, ITask task, Datestamp date, int hours)
			throws DbException;

	/**
	 * Удаляет задачу
	 * 
	 * @param manager
	 *            - менеджер
	 * @param task
	 *            - задача
	 * @throws DbException
	 *             не удалось
	 */
	void dropTask(IManager manager, ITask task) throws DbException;

	/**
	 * Возвращает список задач, удовлетворяющих заданному критерию.
	 * 
	 * @param criteria
	 *            - критерий поиска
	 * @throws DbException
	 *             не удалось
	 * @return список задач
	 */
	List<ITask> getTasks(TaskCriteria criteria) throws DbException;

	/**
	 * Возвращает список всех пользователей вообще
	 * 
	 * @return список пользователей
	 * @throws DbException
	 *             - не удалось
	 */
	List<IPerson> getUsers() throws DbException;

	/**
	 * Возвращает список отметок времени для задачи
	 * 
	 * @param task
	 *            - задача
	 * @return список отметок времени
	 * @throws DbException
	 *             не удалось
	 */
	List<IWorkTime> getWorkTimes(ITask task) throws DbException;

	/**
	 * Возвращает список исполнителей задачи
	 * 
	 * @param task
	 *            - задача
	 * @return список исполнителей
	 * @throws DbException
	 *             не удалось
	 */
	List<IWorker> getWorkers(ITask task) throws DbException;

	/**
	 * Возвращает список, в которых данный менеджер пока не участвует.
	 * 
	 * @param manager
	 *            - менеджер
	 * @return список проектов, в которых менеджер не задействован
	 * @throws DbException
	 *             не удалось
	 */
	List<ITaskProject> getNonjoinedProjects(IManager manager)
			throws DbException;
}
